package com.fs.wechat.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fs.common.http.HttpHelper;
import com.fs.common.pojo.Order;
import com.fs.common.pojo.WechatPayConfig;
import com.fs.common.utils.ConcurrentHashMapCacheUtils;
import com.fs.common.utils.MapUtil;
import com.fs.wechat.constants.WXConstants;
import com.fs.wechat.service.WechatPayService;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.util.SignUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author DeveloperKK
 * @desc
 * @creationTime 2019-08-20 14:51
 * @projectName yuezi-menu
 * @packageName com.fs.console.wechat.service
 */
@Slf4j
@Service
public class WechatPayServiceImpl implements WechatPayService {


    @Autowired
    private WxPayService wxPayService;

    @Override
    public JSONObject code2Session(String code) {
        Map<String, String> params = new HashMap<>();
        WechatPayConfig wxPayConfig = refreshWxPayConfig("JSAPI");
        params.put("appid", WXConstants.APP_ID);
        params.put("secret",WXConstants.SECRET);
        params.put("js_code",code);
        params.put("grant_type","authorization_code");
        String rep = this.post(wxPayConfig.getWxUrl()+ "/sns/jscode2session",params);
        return JSON.parseObject(rep);
    }

    @Override
    public <T> T createOrder( Order order) throws WxPayException {
        T result = null;
        try {
            WechatPayConfig wxPayConfig = refreshWxPayConfig(order.getTradeType());
            SimpleDateFormat dateFormater = new SimpleDateFormat("yyyyMMddHHmmss");
            Date afterDate = new Date(System.currentTimeMillis() + 1800000);
            WxPayUnifiedOrderRequest wxPay = new WxPayUnifiedOrderRequest();
            wxPay.setAppid(wxPayConfig.getAppId());
            wxPay.setMchId(wxPayConfig.getMchId());//商户号
            wxPay.setNonceStr(getNonceStr());//随机字符串
            wxPay.setBody(order.getOrderName());//商品描述
            wxPay.setOutTradeNo(order.getOutTradeNo());//商户订单号
            wxPay.setTotalFee(order.getTotalFee());//标价金额
            wxPay.setSpbillCreateIp(order.getIpAddress());//终端IP
            wxPay.setProductId(order.getId());
            wxPay.setNotifyUrl(wxPayService.getConfig().getNotifyUrl());//通知地址
            wxPay.setTradeType(order.getTradeType());//交易类型
            wxPay.setOpenid(order.getOpenid());//如果是JSAPI，openId是必传的
            wxPay.setTimeStart(dateFormater.format(new Date()));//订单开始时间
            wxPay.setTimeExpire(dateFormater.format(afterDate));//订单失效时间
            wxPay.setSign(SignUtils.createSign(MapUtil.objectToMap(wxPay),"MD5",wxPayConfig.getPartnerKey(),null));
            result = wxPayService.createOrder(wxPay);


        } catch (Exception e) {
            if (e instanceof WxPayException) {
                throw (WxPayException)e;
            }
            e.printStackTrace();
            log.error(e.getMessage());
        }

        return result;
    }
    @Override
    public WxPayOrderNotifyResult wxPayOrderNotifyResult(String xml) throws WxPayException {
        return wxPayService.parseOrderNotifyResult(xml);
    }

    @Override
    public WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxPayException {
        return wxPayService.queryOrder(transactionId,outTradeNo);
    }


    private WechatPayConfig refreshWxPayConfig(String type){
        WxPayConfig config = this.wxPayService.getConfig();
        WechatPayConfig wpc = (WechatPayConfig)ConcurrentHashMapCacheUtils.getCache(WechatPayConfig.CACHE_KEY);
        config.setMchId(wpc.getMchId());
        config.setMchKey(wpc.getPartnerKey());
        String notifyUrl = "JSAPI".equalsIgnoreCase(type)? wpc.getJsNotifyUrl() : wpc.getNativeNotifyUrl();
        config.setNotifyUrl(notifyUrl);
        config.setPayBaseUrl(wpc.getPayUrl());
        this.wxPayService.setConfig(config);
        return wpc;
    }

    private String post(String url,Map<String, String> params ){
         return HttpHelper.Instance().httpPost(url, params);
    }

    private String getNonceStr(){
        return UUID.randomUUID().toString().trim().replaceAll("-", "");
    }

}
